import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
/*
 * 获取类的三种方式
 * Class clazz = Class.forName("包名.类名");
 * Class clazz = 类名.class
 * Class clazz = 对象.getClass();
 * */
public class Main {
    public static void main(String[] args) {
        System.out.println("Test1");
        //操作类
        test1();
        System.out.println("==========================================================================");
        System.out.println("test2");
        //获取父类
        test2();
        System.out.println("==========================================================================");
        System.out.println("test3");
        //获取当前Class的所有父亲接口
        test3();
        System.out.println("==========================================================================");
        System.out.println("test4");
        //操作属性
        test4();
        System.out.println("==========================================================================");
        System.out.println("test5");
        //操作方法
        test5();
        System.out.println("==========================================================================");
        System.out.println("test6");
        //操作构造方法
        test6();
    }
    public static void test1(){
        //通过一个Class对象来操作Person.class文件
        try {

            Class clazz = Class.forName("reflect.Person");
            //类有自己的机构、权限修饰符、特征修饰符、继承、实现接口

            int modifiers = clazz.getModifiers();//获取权限修饰符
            //每一个修饰符用一个整数表示 0 1 2 4 8 16 32 ~
            System.out.println("类的修饰符为：" + modifiers);

            //得名
            String name = clazz.getName();
            String simpleName = clazz.getSimpleName();
            System.out.println("类的全名：" + name);
            System.out.println("类名：" + simpleName);

            //得包
            Package p = clazz.getPackage();
            System.out.println("类的包名：" + p.getName());

            //得父类
            Class sclazz = clazz.getSuperclass();
            System.out.println("类的父类：" + sclazz.getName());

            //调用无参构造方法创建对象
            Person person = (Person) clazz.newInstance();
            System.out.println("调用无参构造方法创建对象：" + person);

        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        }
    }
    public static void test2(){
        ArrayList<String> list = new ArrayList<>();
        Class clayy = ArrayList.class;
        Class sclayy = clayy.getSuperclass();
        System.out.println("ArrayList的父类及其祖先类：");
        while(sclayy != null){
            System.out.println(sclayy.getName());
            sclayy = sclayy.getSuperclass();
        }

    }
    public static void test3(){
        ArrayList<String> list = new ArrayList<>();
        Class claxx = ArrayList.class;
        Class[] interfaces = claxx.getInterfaces();
        System.out.println("ArrayList实现的接口：");
        for(Class c : interfaces){
            System.out.println(c.getName());
        }

    }
    public static void test4(){
        try {
            //通过claww来获取类的属性
            Class claww = Class.forName("reflect.Person");
            //通过名字获取name属性
            Field name = claww.getField("name");
            Field[] fields = claww.getFields();
            for (Field f : fields) {
                System.out.println("Person中的所有public属性：" + f.getName());
            }
            //属性修饰符
            int modifiers = name.getModifiers();
            System.out.println("name的属性修饰符：" + modifiers);
            //属性的类型
            Class type = name.getType();
            System.out.println("name的类型：" + type.getName());

            //属性的名字
            String fname = name.getName();
            System.out.println("name的类型：" + fname);
            //属性赋值
            //1.创建对象
            //2.赋值
            Person person = (Person) claww.newInstance();
            name.set(person,"小明");

            //取值
            String s = (String) name.get(person);
            System.out.println("person中name的值：" + s);
            //获取私有属性
            Field id = claww.getDeclaredField("id");
            // System.out.println("****"+id.getType().getName());
            //设置私有属性可被操作
            id.setAccessible(true);
            id.set(person,20);

            //输出person
            System.out.println("person对象：" + person.toString());


        } catch (ClassNotFoundException | NoSuchFieldException | InstantiationException | IllegalAccessException e) {
            e.printStackTrace();
        }
    }
    public static void test5(){
        try {
            Class clavv = Class.forName("reflect.Person");
            Person person = (Person) clavv.newInstance();
            Method m3 = clavv.getMethod("eat", String.class, int.class);
            Method m4 = clavv.getDeclaredMethod("privateEat", String.class);
            System.out.println("通过方法名获取到的方法："+m3.getName()+"," + m4.getName());
            int modifiers = m3.getModifiers();
            //获取方法修饰符（权限+特征）
            System.out.println("m3的修饰符："+modifiers);
            //获取返回数据类型
            Class type = m3.getReturnType();
            //获取参数列表类型
            Class[] parameterTypes = m3.getParameterTypes();
            //获取方法的抛出异常类型
            Class[] exceptionTypes = m3.getExceptionTypes();
            //获取方法列表


            //执行public方法，同样适用于继承的父类方法

            String result1 = (String) m3.invoke(person, "测试public", 20);
            System.out.println(result1);

            //执行私有方法，
            m4.setAccessible(true);
            String result2 = (String) m4.invoke(person,"测试private");
            System.out.println(result2);

        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }
    public static void test6(){
        Class clauu = Person.class;
        try {
            //无参构造方法
            Constructor con1 = clauu.getConstructor();
            Person person1 = (Person) con1.newInstance();
            //有参构造方法
            Constructor con2 = clauu.getConstructor(String.class, int.class);
            Person person2 = (Person) con2.newInstance("小明", 20);
            System.out.println("输出person2对象：" + person2.toString());
            //其他和普通方法操作基本相同，不再列举

        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }

}
